package org.michaelbel.bottomsheet;

import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.DragInfo;
import ohos.agp.render.Canvas;
import ohos.agp.utils.Point;
import ohos.app.Context;

import org.michaelbel.bottomsheet.util.ResTUtil;

/**
 * Description: 智能的拖拽布局，优先滚动整体，整体滚到头，则滚动内部能滚动的View
 * Create by dance, at 2018/12/23
 */
public class BottomSheetDragLayout extends DirectionalLayout
        implements Component.BindStateChangedListener, Component.DrawTask {
    private static final String TAG = "BottomSheetDragLayout";
    private Component child;
    boolean enableDrag = true; // 是否启用手势拖拽
    boolean dismissOnTouchOutside = true;
    boolean hasShadowBg = true;
    boolean isUserClose = false;

    public BottomSheetDragLayout(Context context) {
        this(context, null);
    }

    public BottomSheetDragLayout(Context context, AttrSet attrSet) {
        this(context, attrSet, null);
    }

    public BottomSheetDragLayout(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        setBindStateChangedListener(this);
        addDrawTask(this);
        setDraggedListener(1, mDragListener);
    }

    int maxY;
    int minY;

    @Override
    public void addComponent(Component childComponent) {
        super.addComponent(childComponent);
        child = childComponent;
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        maxY = child.getHeight();
        minY = 0;
        int lon = getWidth() / 2 - child.getWidth() / 2;
        child.setComponentPosition(lon, getHeight(), lon + child.getWidth(), getHeight() + maxY);
    }

    DraggedListener mDragListener =
            new DraggedListener() {
                Point startPoint;

                @Override
                public void onDragDown(Component component, DragInfo dragInfo) {}

                @Override
                public void onDragStart(Component component, DragInfo dragInfo) {
                    startPoint = dragInfo.startPoint;
                }

                @Override
                public void onDragUpdate(Component component, DragInfo dragInfo) {
                    if (enableDrag) {
                        int ty = (int) (dragInfo.updatePoint.getPointY() - startPoint.getPointY());
                        ty = ty > maxY - 1 ? maxY - 1 : ty;
                        translationY(ty);
                    }
                }

                @Override
                public void onDragEnd(Component component, DragInfo dragInfo) {
                    if (enableDrag) {
                        int ty = (int) (dragInfo.updatePoint.getPointY() - startPoint.getPointY());
                        if (ty > maxY / 2) {
                            close();
                        } else {
                            finishTranslationY(ty);
                        }
                    }
                }

                @Override
                public void onDragCancel(Component component, DragInfo dragInfo) {
                    // Do something
                }
            };

    boolean isScrollUp;

    /**
     * s设置距离
     * @param y1 y
     */
    public void translationY(int y1) {
        y1 = y1 < 0 ? 0 : y1;
        isScrollUp = y1 < 0;
        float fraction = y1 * 1f / maxY;
        if (hasShadowBg) {
            setBackground(ResTUtil.buildDrawableByColorRadius(0, 0));
        }
        if (listener != null) {
            listener.onDrag(y1, fraction, isScrollUp);
        }
        child.setTranslationY(y1);
    }

    /**
     * 完成距离
     * @param y1 y
     */
    public void finishTranslationY(float y1) {
        if (child == null || y1 < 0) {
            return;
        }
        AnimatorValue anim = new AnimatorValue();
        anim.setDuration(200);
        anim.setCurveType(Animator.CurveType.LINEAR); // 匀速
        anim.setValueUpdateListener(
                new AnimatorValue.ValueUpdateListener() {
                    @Override
                    public void onUpdate(AnimatorValue animatorValue, float value) {
                        child.setTranslationY(y1 - y1 * value);
                    }
                });
        anim.start();
    }

    @Override
    public void onComponentBoundToWindow(Component component) {
        isUserClose = true;
    }

    @Override
    public void onComponentUnboundFromWindow(Component component) {
        isScrollUp = false;
        isUserClose = false;
        setTranslationY(0);
    }

    /**
     * 关闭
     */
    public void close() {
        isUserClose = true;
        if (listener != null) {
            listener.onClose();
        }
    }

    /**
     * 设置是否可拖拽
     * @param enableDrag enableDrag
     */
    public void enableDrag(boolean enableDrag) {
        this.enableDrag = enableDrag;
    }

    /**
     * 设置dimiss 触摸关闭
     * @param dismissOnTouchOutside dismissOnTouchOutside
     */
    public void dismissOnTouchOutside(boolean dismissOnTouchOutside) {
        this.dismissOnTouchOutside = dismissOnTouchOutside;
    }

    /**
     * hasShadowBg
     * @param hasShadowBg hasShadowBg
     */
    public void hasShadowBg(boolean hasShadowBg) {
        this.hasShadowBg = hasShadowBg;
    }

    private OnCloseListener listener;

    /**
     * 关闭监听
     * @param listener listener
     */
    public void setOnCloseListener(OnCloseListener listener) {
        this.listener = listener;
    }

    /**
     * 关闭监听接口
     */
    public interface OnCloseListener {
        // 关闭
        void onClose();

        // 拖拽数据
        void onDrag(int y1, float percent, boolean isScrollUp);
    }
}
